package com.taglab.chic.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.util.UrlPathHelper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletContext;
import java.util.Map;
import java.util.Collections;
import java.util.HashMap;
import java.util.Date;
import java.net.URLDecoder;
import java.io.UnsupportedEncodingException;
import java.io.File;
import java.text.SimpleDateFormat;

/**
 *
 */
public abstract class UrlUtils {

  private static final Logger logger = LoggerFactory.getLogger(UrlUtils.class);

  private UrlUtils() {}

  private static final UrlPathHelper urlPathHelper = new UrlPathHelper();

  // XXX Probably a better way of parsing the query string (perhaps in Spring util class?)
  @SuppressWarnings("unchecked")
  public static Map<String, String> parseQueryString(HttpServletRequest request) {
    String queryString = urlPathHelper.getOriginatingQueryString(request);
    logger.debug("queryString: {}", queryString);
    if(queryString != null) {
      try {
        Map<String, String> parameterMap = new HashMap<String, String>();
        queryString = URLDecoder.decode(queryString, "UTF-8");
        for(String element : queryString.split("&")) {
          int separator = element.indexOf("=");
          if(separator != -1) {
            parameterMap.put(element.substring(0, separator), element.substring(separator+1));
          }
        }
        return parameterMap;
      } catch (UnsupportedEncodingException uee) {
        logger.error("Failed to decode queryString");
      }
    }
    return Collections.EMPTY_MAP;
  }

  public static String getContextFile(ServletContext context, HttpServletRequest request, String path) {
    String contextPath = context.getContextPath();
    if(path.startsWith("/")) {
      // Absolute path

      // TODO This context check will return a false negative when the root context path is used (e.g. "") with an absolute reference to a non-root context

      // Check path is in context (add trailing separator to disambiguate context paths, e.g. /aa and /aah)
      if(!path.startsWith(contextPath + "/")) {
        logger.error("Absolute path ({}) does not match context path ({})", path, contextPath);
        return null;
      }

      // Remove context path from path
      return path.substring(contextPath.length());
    } else {
      // Relative to current request (may have been redirected if in a template)

      // Check path is in context
      String requestContextPath = urlPathHelper.getOriginatingContextPath(request);
      if(!requestContextPath.equals(contextPath)) {
        logger.error("Request context path ({}) does not match context path ({})", requestContextPath, contextPath);
        return null;
      }

      // Remove context path from request
      StringBuffer requestPath = new StringBuffer(urlPathHelper.getOriginatingRequestUri(request));
      if (contextPath.length() > 0) {
        requestPath.delete(0, contextPath.length());
      }

      // Get parent directory of request
      int pathEnd = requestPath.lastIndexOf("/");
      if(pathEnd != -1 && pathEnd + 1 != requestPath.length()) {
        requestPath.delete(pathEnd + 1, requestPath.length());
      }

      // Append path to parent directory
      return requestPath.append(path).toString();
    }
  }

  public static String createVersionString(File file) {
    return new SimpleDateFormat("yyMMddHHmm").format(new Date(file.lastModified()));
  }
}
